<script setup lang="ts">
import { NasFile, FileType, FileTypeMap } from '@global/types'
import useFile from './useFile'
import useFileList from './useFileList'
import useRectSelect from './useRectSelect'
import useContextMenu from './useContextMenu'
import useBreadcrumbs from './useBreadcrumbs'
import useUpload from './useUpload'
import useMedioRecorder from './useMedioRecorder'
import { useMusic } from '@/store/useMusic'
import fs from 'filesize'
import { ref } from 'vue'
import useUserInfo from '@/store/useUserInfo'
import fileSize from 'filesize'
import openLocalApp from '@/utils/openLocalApp'

useUserInfo().init()
const music = useMusic()
music.updateMusicList()

const uploadFileInputRef = ref() // 上传文件的按钮
// 文件列表
const { params, fileData, getFileList, getFileListThrottle } = useFileList()
// 面包屑导航栏
const { breadcrumbs, jumbRouter } = useBreadcrumbs()
// 文件
const { selectFileList, preview, getFileThumb, clickFileHandler, dobuleClickFileHandler } = useFile()
// 矩形选框
const { selectRect } = useRectSelect({ selectFileList, fileData })
// 右键菜单
const {
  contextMenu,
  contextMenuOpts,
  showContextMenu,
  clickMenuItem,

  // 创建文件夹
  createDirModel,
  createDir,

  copyList, // 复制列表
  moveList, // 移动列表

  // 重命名
  renameFileModel,
  checkNewFileName,

  downloadQrCodeModel, // 文件二维码

  detailModel, // 详细信息

  downloadList,
  finishList,
  downloadModelShow,
  isDelRawFile,
  isRepeatAll,
  getDownloadIconClassName,
  getDownloadPercentage,
  changeDownloadStatus,
  delDownloadTask,
  delAllDwonloadTasks
} = useContextMenu({
  params,
  fileData,
  selectFileList,
  getFileList,
  uploadFileInputRef
})
// 文件上传
const {
  selectUploadFileList,
  getUploadIcon,
  getUploadStatus,
  dragWrapperShow,
  getFilesByDrag,
  getFilesByClick,
  changeUploadState
} = useUpload({
  fileData,
  getFileListThrottle,
  uploadFileInputRef
})

// 视频录制
const {
  state: medioRecorderState,
  startRecordVideo,
  selectSource,
  uploadVideo
} = useMedioRecorder({ selectUploadFileList })
</script>

<template>
  <div class="flex flex-col bg-gray-100 w-full" @click="contextMenu.show = false">
    <!-- 面包屑导航栏 -->
    <div class="relative">
      <n-breadcrumb class="border-b bg-green-200 p-4">
        <n-breadcrumb-item v-for="(item, i) in breadcrumbs" :key="i" @click="jumbRouter(item)">
          <span>{{ item.title }}</span>
        </n-breadcrumb-item>
      </n-breadcrumb>

      <div class="flex transform top-1/2 right-2 -translate-y-1/2 absolute items-center">
        <div class="space-x-4 right-menu mr-10 text-xl text-green-600 fa">
          <!-- 创建文件夹 -->
          <b class="fa-folder-open" :title="$t('create-dir')" @click="createDirModel.show = true" />
          <!-- 上传文件 -->
          <b class="fa-cloud-upload" :title="$t('upload')" @click="() => ($refs.uploadFileInputRef as any).click()" />
          <b class="fa-cloud-download" :title="$t('download')" @click="downloadModelShow = true" />
          <input ref="uploadFileInputRef" type="file" multiple class="hidden" @change="getFilesByClick" />
          <!-- 录制视频 -->
          <b class="fa-video-camera" :title="$t('recorder-video')" @click="startRecordVideo" />
          <!-- 音乐播放器 -->
          <n-popover placement="bottom">
            <template #trigger>
              <b class="fa-music" />
            </template>
            <!-- 有音乐显示 -->
            <div v-if="music.musicList.length" class="space-y-2 text-center text-gray-600 duration-300 music-item">
              <div @click="music.isPlay ? music.pause() : music.play()">
                {{ music.isPlay ? $t('pause') : $t('play') }}
              </div>
              <div @click="music.playLast">{{ $t('last-song') }}</div>
              <div @click="music.playNext">{{ $t('next-song') }}</div>
              <div class="cursor-pointer" hover="txtbla"></div>
              <div @click="music.$patch({ show: !music.show })">
                {{ music.show ? $t('hidden') : $t('show') }}{{ $t('player') }}
              </div>
            </div>
            <!-- 无音乐显示 -->
            <div
              v-else
              @click="uploadFileInputRef.click"
              class="cursor-pointer text-gray-400 duration-400"
              hover="text-gray-700"
            >
              {{ $t('no-upload-music') }}
            </div>
          </n-popover>
        </div>
      </div>
    </div>

    <div
      class="flex-col flex flex-1 relative overflow-hidden"
      @dragover.prevent="dragWrapperShow = true"
      @contextmenu.prevent="showContextMenu"
    >
      <!-- 文件列表为空 -->
      <n-empty
        v-show="!fileData.list.length"
        :description="$t('drag-file-to-upload')"
        size="huge"
        class="flex h-full w-full absolute justify-center items-center"
      />

      <!-- 矩形文件选中框 -->
      <div v-show="selectRect.show" class="z-1 relative">
        <div class="border bg-blue-500/20 fixed" border="blue-500 dashed" :style="selectRect.style" />
      </div>

      <!-- 上传文件拖拽框 -->
      <div
        v-show="dragWrapperShow"
        class="flex h-full bg-black/50 text-white w-full top-0 left-0 text-3xl z-1 absolute justify-center items-center"
        @dragleave.prevent="dragWrapperShow = false"
        @drop.prevent="getFilesByDrag"
      >
        {{ $t('drag-file-to-upload') }}
      </div>

      <!-- 文件列表容器 -->
      <div class="flex-1 m-4 overflow-y-auto">
        <!-- 右键菜单 -->
        <n-dropdown
          placement="bottom-start"
          trigger="manual"
          :animated="false"
          :x="contextMenu.x"
          :y="contextMenu.y"
          :options="contextMenuOpts"
          :show="contextMenu.show"
          @select="clickMenuItem"
        />

        <div file-wrapper class="h-full">
          <div class="flex flex-wrap relative">
            <!-- 文件列表 -->
            <transition-group
              enter-from-class="opacity-0 transform-gpu -translate-y-1/2"
              leave-to-class="opacity-0 transform-gpu"
              leave-active-class="absolute"
            >
              <div
                v-for="item in [{ id: -1, fileName: '1' } as NasFile, ...fileData.list]"
                :key="item.id"
                class="duration-500"
              >
                <div
                  :file-id="item.id"
                  class="border rounded cursor-pointer flex flex-col m-1 p-1 w-28 relative items-center overflow-hidden"
                  border="transparent dashed"
                  :class="[
                    { '!fixed -top-999': item.id === -1 },
                    {
                      '!border-gray-400 bg-gray-400/50': [...selectFileList, ...copyList, ...moveList].some(
                        ({ id }) => id === item.id
                      )
                    },
                    { 'animate-pulse': [...copyList, ...moveList].some(({ id }) => id === item.id) }
                  ]"
                  hover="!bg-gray-300"
                  @click="clickFileHandler(item)"
                  @dblclick="dobuleClickFileHandler(item)"
                >
                  <img :src="getFileThumb(item)" class="object-contain h-14 w-14" />
                  <div class="mx-auto text-center w-24 truncate" :title="item.fileName">{{ item.fileName }}</div>

                  <div
                    v-if="!item.uploadFinish || (music.isPlay && music.getCurrentMusicInfo?.id === item.id)"
                    class="flex h-full bg-black/60 w-full top-0 left-0 absolute justify-center items-center"
                  >
                    <!-- 正在上传的文件显示进度条 -->
                    <n-progress
                      v-if="!item.uploadFinish"
                      type="circle"
                      :status="getUploadStatus(item)"
                      :percentage="((item.uploaded as number) / (item.fileSize as number)) * 100"
                      class="cursor-pointer duration-300 filter !h-14 !w-14"
                      hover="brightness-85"
                      @click.stop="changeUploadState(item)"
                    >
                      <i class="text-xl fa" :class="getUploadIcon(item)" />
                    </n-progress>

                    <!-- 正在播放的音乐显示播放进度 -->
                    <n-progress
                      v-if="music.isPlay && music.getCurrentMusicInfo?.id === item.id"
                      type="circle"
                      status="info"
                      :percentage="(music.currentTime / music.totalTime) * 100"
                      class="cursor-pointer text-xl duration-300 group filter !h-14 !w-14"
                      hover="brightness-85"
                    >
                      <i class="animate-bounce text-blue-400 fa fa-music" group-hover="hidden" />
                      <i class="text-white fa fa-pause hidden" group-hover="block" @click="music.pause()" />
                    </n-progress>
                  </div>
                </div>
              </div>
            </transition-group>
          </div>
        </div>
      </div>

      <!-- 底部 -->
      <div class="flex py-5 px-8 items-end border-t shadow">
        <!-- <n-progress
          type="line"
          status="success"
          :percentage="50"
          :height="24"
          indicator-placement="inside"
          border-radius="12px 12px 0 0"
          fill-border-radius="12px 0 12px 12px"
          class="!w-[75%]"
        /> -->

        <!-- 分页 -->
        <n-pagination
          v-model:page="fileData.page"
          :page-size="params.size"
          :item-count="fileData.total"
          :on-update:page="(page: number) => params.page = page"
          :on-update:page-size="(size: number) => params.size = size"
          class="ml-auto"
        />
      </div>
    </div>
  </div>

  <!-- 修改文件名 -->
  <n-modal v-model:show="renameFileModel.show">
    <n-card :title="$t('rename-file')" class="w-150">
      <n-input v-model:value="renameFileModel.oldFileName" />

      <template #footer>
        <div class="flex space-x-5 justify-end">
          <n-button @click="checkNewFileName">{{ $t('confirm') }}</n-button>
          <n-button @click="renameFileModel.show = false">{{ $t('cancel') }}</n-button>
        </div>
      </template>
    </n-card>
  </n-modal>

  <!-- 创建文件夹 -->
  <n-modal v-model:show="createDirModel.show">
    <n-card :title="$t('create-dir')" class="w-150">
      <n-input v-model:value="createDirModel.dirName" />

      <template #footer>
        <div class="flex space-x-5 justify-end">
          <n-button @click="createDir">{{ $t('confirm') }}</n-button>
          <n-button @click="createDirModel.show = false">{{ $t('cancel') }}</n-button>
        </div>
      </template>
    </n-card>
  </n-modal>

  <!-- 文件二维码 -->
  <n-modal v-model:show="downloadQrCodeModel.show" preset="card" :title="downloadQrCodeModel.fileName" class="w-100">
    <img :src="downloadQrCodeModel.dataBase64" class="mx-auto" />
  </n-modal>

  <!-- 预览图片 -->
  <n-image-group ref="previewImgsRef" show-toolbar-tooltip>
    <div class="hidden">
      <n-image
        v-for="item in fileData.list.filter(item => item.fileType === FileType.image && item.uploadFinish)"
        :id="`previewImg${item.id}`"
        :key="item.id"
        :refs="`previewImg${item.id}`"
        :src="`${$useEnv().nasFileUrl}/${item.filePath}`"
      />
    </div>
  </n-image-group>

  <!-- 预览视频 -->
  <n-modal v-model:show="preview.video.show">
    <video
      :src="preview.video.url"
      controls
      class="object-contain max-w-90vw max-h-90vh"
      @error=";(preview.video.show = false) || $message.error($t('no-support-preview-video'))"
    />
  </n-modal>

  <!-- 预览文档 -->
  <n-modal v-model:show="preview.document.show" :title="preview.fileName" preset="card" class="h-90vh w-90vw">
    <div class="border rounded h-full overflow-y-auto">
      <iframe
        :src="preview.document.url"
        frameborder="0"
        class="h-full w-full"
        @error=";(preview.document.show = false) || $message.error($t('no-support-preview-document'))"
      />
    </div>
  </n-modal>

  <!-- 详细信息 -->
  <n-modal v-model:show="detailModel.show" preset="card" :title="detailModel.fileInfo.fileName" class="w-100">
    <div class="flex flex-col space-y-2 detail-info">
      <div>
        <b>{{ $t('file-id') }}</b>
        <span>{{ detailModel.fileInfo.id }}</span>
      </div>
      <div>
        <b>{{ $t('file-type') }}</b>
        <span>{{ $t(FileTypeMap[detailModel.fileInfo.fileType + '']) }}</span>
      </div>
      <div>
        <b>{{ $t('file-path') }}</b>
        <span>{{ detailModel.fileInfo.filePath.replace('@@@', '/') }}</span>
      </div>
      <div v-if="!detailModel.fileInfo.uploadFinish && detailModel.fileInfo.uploaded">
        <b>{{ $t('uploaded') }}</b>
        <span>{{ fs(detailModel.fileInfo.uploaded) }}</span>
      </div>
      <div v-if="detailModel.fileInfo.fileSize">
        <b>{{ $t('file-size') }}</b>
        <span>{{ fs(detailModel.fileInfo.fileSize) }}</span>
      </div>
      <div>
        <b>{{ $t('create-time') }}</b>
        <span>{{ $formatTime(detailModel.fileInfo.createTime) }}</span>
      </div>
    </div>
  </n-modal>

  <n-modal
    v-model:show="medioRecorderState.desktopSource.show"
    preset="card"
    :title="$t('select-content-to-share')"
    class="w-2/3"
  >
    <n-tabs v-model:value="medioRecorderState.desktopSource.activeTab" animated>
      <n-tab-pane
        v-for="(tab, key) in medioRecorderState.desktopSource.sources"
        :key="key"
        :name="key"
        :tab="$t(key)"
        class="flex space-x-10 overflow-x-auto"
      >
        <div
          v-for="item in tab"
          :key="item.id"
          class="flex flex-col items-center py-5 group cursor-pointer"
          :title="item.name"
          @click="selectSource(item)"
        >
          <img
            :src="item.img"
            class="w-50 h-25 object-cover duration-300"
            border="4 transparent"
            group-hover="border-green-400"
          />
          <span class="w-50 text-center truncate">{{ item.name }}</span>
        </div>
      </n-tab-pane>
    </n-tabs>
  </n-modal>

  <!-- 预览录制的视频 -->
  <n-modal v-model:show="medioRecorderState.show" preset="card" class="w-80vw">
    <div class="flex flex-col h-80vh justify-center items-center">
      <video :src="medioRecorderState.url" controls class="object-contain max-w-[90%] max-h-[70%]" />
      <div class="flex space-x-10 mt-10">
        <n-button type="primary" @click="uploadVideo">{{ $t('upload') }}</n-button>
        <n-button @click="medioRecorderState.show = false">{{ $t('cancel') }}</n-button>
      </div>
    </div>
  </n-modal>

  <n-modal v-model:show="downloadModelShow" preset="card" class="w-80vw" title="下载列表">
    <div class="flex justify-end items-center pb-4 border-b">
      <div class="mr-4">{{ $t('repeat-all-files-or-dirs') }}</div>
      <n-switch v-model:value="isRepeatAll" />
      <div class="ml-12 mr-4">{{ $t('delete-raw-files') }}</div>
      <n-switch v-model:value="isDelRawFile" />
      <n-button type="error" class="ml-12" size="small" :title="$t('delete-all-files')" @click="delAllDwonloadTasks">
        <i class="fa fa-trash"></i>
      </n-button>
    </div>
    <div class="divide-y-1 h-60vh overflow-y-auto pr-5 text-sm">
      <div
        v-for="item in downloadList"
        :key="item.dId"
        class="flex space-x-5 py-4 items-center"
        :class="{ 'line-through text-red-400': item.status === 'error' }"
      >
        <div class="w-32 truncate" :title="item.fileName">{{ item.fileName }}</div>
        <n-progress
          type="line"
          :percentage="getDownloadPercentage(item)"
          class="duration-1000 overflow-hidden whitespace-nowrap"
          :class="finishList.find(({ id }) => id === item.id) ? 'flex-[0]' : 'flex-1'"
        >
          {{ getDownloadPercentage(item) }}%
        </n-progress>
        <div
          class="flex-1 duration-1000 truncate underline underline-blue-400 text-blue-400 cursor-pointer"
          :class="finishList.find(({ id }) => id === item.id) ? 'flex-1' : 'flex-[0]'"
          :title="item.realFilePath"
          @click="openLocalApp(item.realFilePath)"
        >
          {{ item.realFilePath }}
        </div>
        <div class="min-w-40 text-center">{{ fileSize(item.loaded || 0) }}/{{ fileSize(item.fileSize || 0) }}</div>
        <i class="fa" :class="getDownloadIconClassName(item)" @click="changeDownloadStatus(item)" />
        <i
          class="fa cursor-pointer text-red-400 fa-close duration-300"
          hover="text-red-600"
          :title="$t('delete-file')"
          @click="delDownloadTask(item)"
        />
      </div>
      <div v-show="!downloadList.length" class="h-full w-full flex">
        <div class="m-auto text-xl text-green-400">{{ $t('no-download-task') }}</div>
      </div>
    </div>
  </n-modal>
</template>

<style scoped>
.music-item div {
  @apply cursor-pointer duration-300 hover:text-black;
}
.right-menu b {
  @apply cursor-pointer duration-300 hover:text-green-700;
}
.detail-info b {
  @apply min-w-20 inline-block;
}
</style>
